package com.bilibili.server.service;

import com.bilibili.server.entity.Video;
import com.bilibili.server.repository.VideoRepository;
import com.bilibili.server.utils.RedisUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageImpl;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import jakarta.persistence.EntityManager;
import jakarta.persistence.PersistenceContext;
import jakarta.persistence.Query;

import java.util.List;
import java.util.Optional;

@Service
@Transactional
public class VideoService {
    @Autowired
    private VideoRepository videoRepository;

    @Autowired
    private RedisUtil redisUtil;

    @PersistenceContext
    private EntityManager entityManager;

    // 获取推荐视频列表
    public Page<Video> getRecommendedVideos(int page, int pageSize) {
        Pageable pageable = PageRequest.of(page - 1, pageSize);
        // 根据API文档要求：推荐视频按收藏数(collect_count)降序排序
        // 使用自定义查询，因为JPA Repository中没有现成的方法
        String jpql = "SELECT v FROM Video v WHERE v.status = :status ORDER BY v.collectCount DESC";
        Query query = entityManager.createQuery(jpql, Video.class);
        query.setParameter("status", 1);
        
        // 手动分页
        long total = videoRepository.countByStatus(1);
        List<Video> content = query.setFirstResult((page - 1) * pageSize)
                                  .setMaxResults(pageSize)
                                  .getResultList();
        
        return new PageImpl<>(content, pageable, total);
    }

    public List<Video> getRecommendedVideos() {
        String cacheKey = "videos:recommended";
        
        List<Video> videos = redisUtil.getCache(cacheKey, List.class);
        
        if (videos == null) {
            videos = videoRepository.findTop15ByStatusOrderByCreatedAtDesc(1);
            // 设置缓存，过期时间30分钟
            redisUtil.setCache(cacheKey, videos, 1800L, true);
        }
        
        return videos;
    }

    // 获取最新视频列表
    public Page<Video> getLatestVideos(int page, int pageSize) {
        Pageable pageable = PageRequest.of(page - 1, pageSize);
        return videoRepository.findByStatusOrderByCreatedAtDesc(1, pageable);
    }

    public List<Video> getLatestVideos() {
        String cacheKey = "videos:latest";
        
        List<Video> videos = redisUtil.getCache(cacheKey, List.class);
        
        if (videos == null) {
            videos = videoRepository.findTop15ByStatusOrderByCreatedAtDesc(1);
            // 设置缓存，过期时间30分钟
            redisUtil.setCache(cacheKey, videos, 1800L, true);
        }
        
        return videos;
    }

    // 获取热门视频列表
    public Page<Video> getHotVideos(int page, int pageSize) {
        Pageable pageable = PageRequest.of(page - 1, pageSize);
        return videoRepository.findByStatusOrderByViewCountDesc(1, pageable);
    }

    public List<Video> getHotVideos() {
        String cacheKey = "videos:hot";
        
        List<Video> videos = redisUtil.getCache(cacheKey, List.class);
        
        if (videos == null) {
            videos = videoRepository.findTop15ByStatusOrderByViewCountDesc(1);
            // 设置缓存，过期时间30分钟
            redisUtil.setCache(cacheKey, videos, 1800L, true);
        }
        
        return videos;
    }

    // 获取幻灯片视频列表（最多6个）
    public List<Video> getSlideVideos() {
        String cacheKey = "videos:slide";
        
        List<Video> videos = redisUtil.getCache(cacheKey, List.class);
        
        if (videos == null) {
            // 根据API文档要求：幻灯片视频按点赞数(like_count)降序排序
            // 使用自定义查询，因为JPA Repository中没有现成的方法
            String jpql = "SELECT v FROM Video v WHERE v.status = :status ORDER BY v.likeCount DESC";
            Query query = entityManager.createQuery(jpql, Video.class);
            query.setParameter("status", 1)
                 .setMaxResults(6); // 最多返回6个视频
            videos = query.getResultList();
            
            // 设置缓存，过期时间1小时
            redisUtil.setCache(cacheKey, videos, 3600L, true);
        }
        
        return videos;
    }

    // 根据类别获取视频列表
    public Page<Video> getVideosByCategory(int categoryId, int page, int pageSize) {
        Pageable pageable = PageRequest.of(page - 1, pageSize);
        return videoRepository.findByCategoryIdAndStatus(categoryId, 1, pageable);
    }

    public List<Video> getVideosByCategoryId(Long categoryId) {
        String cacheKey = "videos:category:" + categoryId;
        
        List<Video> videos = redisUtil.getCache(cacheKey, List.class);
        
        if (videos == null) {
            videos = videoRepository.findByCategoryIdAndStatus(categoryId, 1);
            // 设置缓存，过期时间30分钟
            redisUtil.setCache(cacheKey, videos, 1800L, true);
        }
        
        return videos;
    }

    // 获取视频详情
    public Video getVideoDetail(Long videoId) {
        // 缓存键
        String cacheKey = "video:detail:" + videoId;
        
        // 先从缓存获取
        Video video = redisUtil.getCache(cacheKey, Video.class);
        
        if (video == null) {
            // 缓存不存在，从数据库获取
            Optional<Video> videoOptional = videoRepository.findById(videoId);
            if (videoOptional.isPresent()) {
                video = videoOptional.get();
                // 设置缓存，过期时间1小时
                redisUtil.setCache(cacheKey, video, 3600L, true);
                // 添加到布隆过滤器
                redisUtil.addToBloomFilter(cacheKey);
            }
        } else {
            // 缓存存在，异步更新观看次数
            incrementViewCount(videoId);
        }
        
        return video;
    }

    public void incrementViewCount(Long videoId) {
        // 先更新Redis计数器
        String counterKey = "video:view:" + videoId;
        redisUtil.incrementCounter(counterKey, 1);
        
        // 将视频ID加入更新队列，由定时任务批量更新数据库
        redisUtil.queueViewCountUpdate(videoId);
    }
}